home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / me_cd22.zip / DOC.ZIP / MUTT2.DOC < prev    next >
Text File  |  1992-04-27  |  37KB  |  888 lines

  1. ========================================================================
  2. ==     The Mutt2 Programming Language         Craig Durland 9/89 10/91 ==
  3. ========================================================================
  4.  
  5. Here is the documentation for the core Mutt2 programming language.
  6. There are probably many extensions, depending on what application Mutt
  7. is embedded in.  See the documentation for the application for more info.
  8.  
  9.  
  10.              Copyright 1991 Craig Durland
  11.     Distributed under the terms of the GNU General Public License.
  12.   Distributed "as is", without warranties of any kind, but comments,
  13.            suggestions and bug reports are welcome.
  14.  
  15. ======================================================================
  16. ==            Syntax                        ==
  17. ======================================================================
  18.  
  19. symbol    action
  20.   (    evaluate expression
  21.   )    end expression
  22.   {    start block
  23.   }    end block
  24.  
  25. SYNTAX
  26.   pgm   : {exp [exp ...]}, {}
  27.   exp   : (fcn [args]), (var [args]), var, const, ()
  28.   const : number (123, 0xAbC), string ("abc", 'abc'), TRUE, FALSE
  29.   arg   : block
  30.   block : pgm, exp or const
  31.   fcn   : a Mutt function (such as + or while) or defined function.
  32.  
  33. ======================================================================
  34. ==            Data Types                    ==
  35. ======================================================================
  36.  
  37. Mutt is a typed language.
  38.  
  39.   Type        id    What it is
  40.   ----        --    ---- --    --
  41.   BOOLEAN    0x05    TRUE or FALSE.
  42.   BLOB        0x06    A pointer to a block of data.
  43.   NUMBER    0x03    32 bit signed integer.
  44.   STRING    0x08    A bunch of characters.
  45.   LIST        0x09    A list of things.
  46.   VOID        0x01    A type of nothing.
  47.   FCNPTR    0x07    A pointer to a function.
  48.   CHARACTER    0x0A    This is not a real data type.  It is a helper
  49.             type.
  50.   REAL        0x04    Not implemented.
  51.  
  52. Id is a numeric constant that is used to identify a data type.  They are
  53.   used in Mutt programs when you need to talk about types (see
  54.   convert-to).
  55.  
  56. List Syntax
  57.   Sometimes I'll need to refer to the contents of a list.  To do that,
  58.     I'll use [<first element> <next element> ...].  Everything in "[]"
  59.     are the contents of the list.  "[]" by itself means the empty list.
  60.  
  61. ======================================================================
  62. ==                Return Values                ==
  63. ======================================================================
  64.  
  65. All blocks "return" a value.  Pgms return the value of the last exp
  66.   executed.  Note that a pgm can return values of different types.
  67. The class of a return value can be one of:
  68.   BOOLEAN, BLOB, NUMBER, STRING, LIST, VOID, FCNPTR.
  69.  
  70. ======================================================================
  71. ==             Variables (aka vars)                ==
  72. ======================================================================
  73. CREATION
  74.   Vars must be created before they can be used.
  75.   Global vars are initialized to:
  76.       bool            : FALSE
  77.       int, small-int, byte    : 0
  78.       string            : ""
  79.       list            : empty
  80.   Most Local vars are NOT initialized (ie they contain garbage when
  81.     created).  Local strings and lists are initialized the same as
  82.     globals.
  83. EVALUATION & ASSIGNMENT
  84.   Vars behave like fcns, ie (var) evaluates the var (returns its value)
  85.     and (var val) passes val to the var for assignment.  (var val)
  86.     returns val.  If you just want to evaluate a var, you can treat it
  87.     like a const - ie "var" is equivalent to "(var)".  Note, however,
  88.     doing this may cause logic bugs if var also happens to be the name
  89.     of a const (since the const is locked out).  See GOTCHAS.  In some
  90.     cases, (var) and var don't mean the same thing - see pointer.
  91.   Cascading assignment:  you can assign multiple vars the same value.
  92.     eg (int x y z)(x (y (z 123))) assigns 123 to x, y and z.
  93.     eg (int x)(string s 20)(x (convert-to NUMBER (s "123"))) sets s to
  94.       "123" and x to 123.
  95. SCOPE
  96.   The scope of a variable is the same as the pgm it is created in.
  97.   A variable created outside of a fcn (defun) is global - ie anybody
  98.     can get at it.  Global variables are local to the file (and any
  99.     included file(s)) they are created in.
  100.   For example:
  101.     If foo.mut contains:
  102.       (int foo)        ; declare and create global var "foo"
  103.       (defun "hoho" { (int bar) (bar foo) })
  104.       (foo 123)        ; assign 123 to foo
  105.     (load "foo.mut") will create a global var foo.  (hoho)
  106.     creates bar and sets it to 123.  hoho is done and bar is freed.
  107.     foo is still alive and equal to 123.
  108.  
  109. ======================================================================
  110. ==            Functions and Keywords                ==
  111. ======================================================================
  112. Everything in this list is a function (except those that have a return
  113.   class of zip).
  114.  
  115. A TOKEN is a bunch of letters, eg foo.
  116.  
  117. (KEYWORD args)        [arg class(s) : return class]
  118. -------- -----        ---- -------- -    ------ ------
  119.  
  120. ; (semi-colon)    A comment that extends to the end of the line
  121.  
  122. (== value value ...)          [STRINGs, NUMBERs or BOOLEANs : BOOLEAN]
  123.   Test 2 or more items for equality.  
  124.   You can only compare like types - eg (== "123" 123) is illegal.
  125.   eg (== foo 1), (== "one" "two"), (== (+ foo 3) bar 5).
  126. (!= value value)                 [NUMBER NUMBER : BOOLEAN]
  127.     Same as == but nonequality.  Only 2 items.
  128. (<  value1 value2) TRUE if value1 <  value2.     [NUMBER NUMBER : BOOLEAN]
  129. (<= value1 value2) TRUE if value1 <= value2.     [NUMBER NUMBER : BOOLEAN]
  130. (>  value1 value2) TRUE if value1 >  value2.     [NUMBER NUMBER : BOOLEAN]
  131. (>= value1 value2) TRUE if value1 >= value2.     [NUMBER NUMBER : BOOLEAN]
  132. (+  values)                        [NUMBERs : NUMBER]
  133.     Add a bunch of numbers  eg (+ 1 2 3 4) => 1+2+3+4
  134. (-  values)                        [NUMBERs : NUMBER]
  135.     Subtract a bunch of numbers eg (- 1 2 3 4) => 1-2-3-4 = -8
  136. (*  values)    multiply a bunch of numbers        [NUMBERs : NUMBER]
  137. (/  values)    divide a bunch of numbers        [NUMBERs : NUMBER]
  138. (+= var values)                      [TOKEN NUMBERs : NUMBER]
  139.     Add value(s) to var and assign it back to the var.  Returns the result.
  140.     Short hand for (var (+ var values)).
  141.     eg (+= foo 1) (+= foo fud 3) 
  142. (-= var values)      Subtract value from var.      [TOKEN NUMBERs : NUMBER]
  143. (*= var values)      Multiply var by value.      [TOKEN NUMBERs : NUMBER]
  144. (/= var values)      Divide var by value.          [TOKEN NUMBERs : NUMBER]
  145.  
  146. "string"
  147.   String constant.
  148.   Special characters:
  149.     \    quote the next character.  "\\" => '\'   "\^" => '^'
  150.     ^    convert the next character to a control character (make sure that
  151.       the letter is UPPERCASE!).  eg "^A"
  152.     Note: escape == ^[.
  153. 'string'
  154.   String constant.
  155.   No special characters except '' reduces to ' ie if you need a string
  156.     like "don't", you can use 'don''t'.
  157.   This form is handy for regular expressions.
  158.  
  159. (and values)                 [BOOLEAN [BOOLEAN ...] : BOOLEAN]
  160.   Logically and a bunch of things
  161.   The first FALSE value will terminate (ie the rest of the and will
  162.     not be evaluated).
  163.   Example:
  164.     (and (previous-line) (foo)):  If previous-line returns TRUE, foo is
  165.       called and that will be the result of the and.  If previous-line
  166.       returns FALSE, the and returns FALSE and foo is not called.
  167.   See also: or.                                  
  168. (arg n)                              [NUMBER : any class]
  169.   Get the nth argument from the parameter list.
  170.   The arguments are numbered 0,1...,(nargs)-1
  171.   eg (fcn 1 "two" (three)) has 3 arguments:  numeric 1, string "two" and
  172.     whatever fcn three returns.  (arg 0) returns 1, (arg 1) returns
  173.     "two", (arg 2) returns result of (three).  (arg 3), (arg -1), etc
  174.     error.
  175.   Notes:
  176.     You cannot set a arg unless it is a pointer.
  177.     See defun for how you can name the args.
  178.   See also: ask, defun, nargs.
  179. (array type name dimensions)   [TOKEN TOKEN NUMBERs [TOKEN NUMBERs] : zip]
  180.   Create an array.  Types allowed: bool, int, small-int.
  181.   (array int x 5 z 7) creates two arrays:  x with 5 ints and z with 7.
  182.   (array int y 2 3) creates an array with 2 rows of 3 ints each.
  183.   (x 3 123) sets the third element of x to 123.
  184.   (x 3) returns 123.
  185. (ask prompt(s))                       [any class(s) ... : STRING]
  186.   Get the next argument from the argument list; if the argument list is
  187.     empty, query the user.  Aways returns a string - if the arg is not a
  188.     string, it is converted to one.
  189.   eg if (foo (ask "foo = ")) is in fud then (fud "hoho") will pass "hoho"
  190.     to foo.  (fud) will cause the message "foo = " to appear and will wait
  191.     for a response to assign to foo.
  192.   You can force the pgm to query the user with (ask-user).  If you do
  193.     this, you will need one per ask.  The next unmodified (ask) will
  194.     behave as above.
  195.   (ask) can take more than one argument.  For example, if foo is 123 then
  196.     (ask "foo is currently " foo ".  Change it to: ") might prompt:
  197.     "foo is currently 123.  Change it to: ".
  198.   Notes:
  199.     Be careful if you mix arg lists and asks.  It can be confusing (to
  200.       the programmer) if you try to get some args via (arg n) and others
  201.       via (ask).  In this case, you should use interactive asks to keep
  202.       ask out of the arg list.  Use nargs and arg if you must mix (to
  203.       implement your own ask like functionality) and will be asking for
  204.       an arg starting after the first one.
  205.     If not interactive, each ask will get the next arg from the arg
  206.       list.  The first ask gets a copy of the first arg, the second ask
  207.       gets the a copy of the second arg, etc.  until there are no more
  208.       args.  After that, next ask will abort the program.  There is no
  209.       way to restart ask.
  210.     Ask doesn't change the arg list - you can ask away and still get at
  211.       any arg with (arg).
  212.   See also: arg, ask-user, convert-to, arg, nargs.
  213. (ask-user)                              [zip : VOID]
  214.   The next ask will query the keyboard and not the program args.
  215.   Turned off after every ask.
  216.   See also: ask.
  217.  
  218. (bool var [var ...])                 [TOKEN [TOKEN ...] : zip]
  219.   Create one or more boolean variables.  If in a defun, the variable is
  220.     local to that defun, otherwise it is global.
  221.   Evaluation: var                     [TOKEN : BOOLEAN]
  222.   Assignment: (var value)             [TOKEN BOOLEAN : BOOLEAN]
  223.   Example: (bool foo)(foo TRUE)  ;; create and set "foo" TRUE
  224.   See also: int, string, list, array.
  225. (break)                                   [zip : zip]
  226.   Get out of the smallest enclosing for or while loop.  The loop then
  227.     retuns the value of the last block executed.
  228.   See also: continue, for, while.
  229. (byte var [var ...])                 [TOKEN [TOKEN ...] : zip]
  230.   Evaluation: var                      [TOKEN : NUMBER]
  231.   Assignment: (var value)               [TOKEN NUMBER : NUMBER]
  232.   Allocate 8 bit unsigned integers.
  233.   The range of a byte is [0 : 255].
  234.   Note that a NUMBER may not fit in a byte.  If not, the number will be
  235.     truncated to fit.
  236.   See also: int, small-int, array, bool.
  237.  
  238. (cond test body ...)
  239.         [[BOOLEAN, block, [BOOLEAN, block ...]] : last block executed]
  240.   Same as  nested  if's.  If the  test is TRUE  then the next  block  is
  241.     executed and the cond is ended.  Otherwise the next block is skipped
  242.     and the cycle repeats.
  243.   eg
  244.   (string str)(str (ask "str = "))
  245.   (cond
  246.     (== str "one") (msg "number 1")
  247.     (== str "foo") (msg "bar")
  248.     TRUE (msg str " is not something I know about.")
  249.   )
  250.   See also: switch.
  251. (concat parameters)                   [anything ... : STRING]
  252.   Concatenate parameters.
  253.   eg (concat "foo = " foo) returns "foo = 123" if foo is 123 or "123".
  254. (const name value [name value ...])    [TOKEN BOOLEAN|NUMBER|STRING : zip]
  255.   Create one or more constants.  Used like other constants (such as
  256.     numbers, strings, etc).
  257.   Precedence: args, local vars, global vars, pgms, consts.
  258.   eg
  259.     (const foo 123 bar "hoho")
  260.     (msg foo bar)    ;; this prints "123hoho")
  261.   Notes:
  262.     Do not use ()'s around constants - they are for functions only.
  263.     See GOTCHAS.
  264. (continue)                               [zip : zip]
  265.   Go to the bottom of the smallest enclosing for or while loop.
  266.     If in a for loop, this means the inc part.
  267.   See also: break, for, while.
  268. (convert-to type value)                       [NUMBER any : type]
  269.   Convert a value of one data type to another type.
  270.   Valid conversions:
  271.     BLOB to:
  272.       No valid conversions.
  273.     BOOLEAN to:
  274.       NUMBER:      TRUE -> 1 and FALSE -> 0
  275.     FCNPTR to:
  276.       No valid conversions.
  277.     LIST to:
  278.       No valid conversions.
  279.     NUMBER to:
  280.       STRING:     same as (concat).  eg 123 -> "123"
  281.       CHARACTER: 0x33 -> "3"
  282.       BOOLEAN:     0 -> FALSE and everything else -> TRUE
  283.     STRING to:
  284.       NUMBER:     "123" -> 123
  285.       CHARACTER: "3" -> 0x33
  286.     VOID to:
  287.       No valid conversions.
  288.    The numeric constants for the data types are in the data types section.
  289.  
  290.   eg (foo (convert-to NUMBER (ask "A number please: ")))
  291.   Note: To convert a number into a string, you can also use concat.
  292.     eg (string s 20)(s (concat 123)) will convert numeric 123 into a
  293.     string and assign it to s.  This is the same as (s (convert-to
  294.     STRING 123))
  295.   See also: ask.
  296.  
  297. (defun name [arglist] [modifier(s)] pgm   [name ...])
  298.                 [TOKEN [([type] TOKEN)...] [TOKENs] pgm : zip]
  299.   Define a function.  Multiple functions can be defined.
  300.   Comments and whitespace have no performance or size penalty, so use
  301.     them.
  302.   You can optionally name the arg list.  
  303.     ([type] name [dimension(s)] [name [dimension(s)]] ...) ...
  304.     int, small-int and byte all mean NUMBER (since all numerics are
  305.     promoted to NUMBER when passed).  Array subscripts are used to
  306.     determine the dimension the passed in array - the first dimension is
  307.     a placeholder (as in C).  Arg type is optional - if not used, no
  308.     assumations are made about the the arg (ie it will be type checked
  309.     at runtime if needbe).  If an arg is typed, what ever is passed in
  310.     is assumed to be of the correct type - it is not checked.
  311.   Modifiers are used to put conditions on a function.
  312.     Modifier : What It Does
  313.     -------- - ---- -- ----
  314.     HIDDEN     Only functions defined after this one can reference it.
  315.     MAIN       This function will be executed when it is loaded.
  316.   MAIN is a special function name.  It defines a function that is
  317.     executed at load time (the same as a function marked MAIN) and can
  318.     not be called by anyone.  Use MAINs to do things that only need to
  319.     be done once before anything else is done (for example, initializing
  320.     some variables).  Use the modifier MAIN if you also want to be able
  321.     to repeat things at other times.  There is no limit on the number of
  322.     MAIN functions or functions marked MAIN.  MAINs are called in the
  323.     order that they are defined.  Functions marked MAIN are called
  324.     alphabetically.
  325.   For example:
  326.     (defun
  327.       foo { (msg "this is foo") }    ; (foo) prints "this is foo"
  328.       bar (int x y)(string s)    ; bar has 3 args: 2 numbers and a string
  329.         {
  330.       (msg s)    ; same as (msg (arg 2))
  331.       (msg (+ x y))    ; same as (msg (+ (arg 0)(arg 1)))
  332.     }
  333.       fred (z) { (msg z (arg 1)) }    ; print the first and second args
  334.       sam MAIN { (msg "sam") }        ; sam is run at load time
  335.       MAIN { (msg "MAIN is run only at load time") }
  336.     )
  337.   Notes:
  338.     You can not assign to an arg unless it is a pointer.
  339.   See also: arg, pointer, the example pgms.
  340. (done)                                   [zip : zip]
  341.   Exit smallest enclosing pgm.
  342.   See also: halt.
  343.  
  344. (extract-element object-name n)
  345.                             [LIST NUMBER : object]
  346.                           [STRING NUMBER : STRING]
  347.   Make a copy of the nth element of a list or string.
  348.   This is the same as (atomize (extract-elements object-name n 1))
  349.     except there is no atomize function.  For example, extracting a
  350.     number from a list results in a number.  If you had used
  351.     extract-elements, it would have returned a list with number in it.
  352.   See extract-elements for how n can modified by the function.
  353.   In the STRING case, this function is the same as
  354.     (extract-elements string n 1).
  355.   Examples:
  356.     (extract-element "123" 1) => "2"
  357.     (extract-element ["123" 4 5] 1) => 4
  358.     (extract-element  [] n) => []
  359.   See also:  extract-elements, insert-object, remove-elements,
  360.     length-of, list.
  361. (extract-elements object-name n z)
  362.                            [LIST NUMBER NUMBER : LIST]
  363.                        [STRING NUMBER NUMBER : STRING]
  364.   Starting at element n, copy of z elements of a list or string to a new
  365.     list or string (0 == first element)
  366.   If (z <= 0) or (n > (length-of object)) or (object == []), returns [].
  367.   If n or z is < 0 then the length of the object is added to them.
  368.   If n > (length-of object), it is set after the last element of the
  369.     object.
  370.   If ask for more elements than are available, returns as many as can.
  371.   Examples:
  372.     (extract-elements "123" 1 1) => "2"
  373.     (extract-elements ["123" 4 5] 0 2) => ["123" 4]
  374.     (extract-elements ["123" 4 5] 1 1) => [4]
  375.     (extract-elements [] n z) => []
  376.   extract-elements also acts like Mock Lisp's substr:
  377.     (extract-elements "foobar" 0 3) => "foo"
  378.     (extract-elements "foobar" -1 1) => "r"
  379.     (extract-elements "foobar" 0 -1) => "fooba"
  380.     (extract-elements "foobar" 3 100) => "bar"
  381.     (extract-elements "foobar" 50 100) => ""
  382.   See also:  extract-element, insert-object, remove-elements, length-of,
  383.     list.
  384.  
  385. FALSE                               [zip : BOOLEAN]
  386.   The boolean constant FALSE.
  387. (floc function-name [args])
  388.      [TOKEN|STRING : BLOB] or [TOKEN|STRING any : last block executed]
  389. !!! oh god ack!
  390.   Return the address of a internal-function or call a function (where
  391.     internal-function is ask, concat, convert-to, extract-element,
  392.     extract-elements, insert-object, length-of, msg, remove-elements, a
  393.     pgm or the name of an external token (see the compiler -t option).
  394.     A function-name is either a token (such as foobar), a string (such
  395.     as "foobar") or a function that returns a string (such as (foobar)).
  396.   Note that most of the keywords and functions in this list are not
  397.     "real" functions - ie they have no address and can't be called from
  398.     floc (the exceptions are the internal functions mentioned above).
  399.   If given args, a function call is generated.  If you want to call a
  400.     function that has no args, use () as the args list
  401.     (eg "(floc "foobar" ())").
  402.   Example:
  403.     (defun
  404.       add (pointer defun plus) (x y)
  405.     { (msg x " + " y " = " (plus x y)) }
  406.       add-two-numbers (int a b) { (+ a b) }
  407.       silly-add (a b) { "three" }
  408.     )
  409.     (add (floc add-two-numbers) 1 2)    ; 1 + 2 = 3
  410.     (add (floc silly-add) "one" "two")    ; one + two = three
  411.   Example:
  412.     (defun
  413.       one { "two" }
  414.       two { "this is a test" }
  415.     )
  416.     (msg (floc (one)()))        ;; this prints: this is a test
  417.   Notes:
  418.     (floc foobar) returns the address of a already defined function.
  419.       Its an error if foobar is not defined in the same file (or any
  420.       included files) as the floc.  The order in which the address is
  421.       resolved is:  internal-functions (see above), an already defined
  422.       pgm, an external token or a pgm defined after the floc.  Given
  423.       these rules, you should be careful about name overloading.
  424.     (floc "foobar"):  The location of foobar is resolved at runtime.
  425.       This is slower and generates more code but always works (if foobar
  426.       really is a function and not a typo).  Note that this method does
  427.       not work for internal-functions or external tokens that don't also
  428.       have a name list for the tokens.
  429.   See also: loc, defun, pointer, qsort (in the EXAMPLE PGMS below)
  430. (for init test inc body)
  431.         [block, BOOLEAN, block, block : FALSE (unless break used)]
  432.   A for next loop:  perform init once.  Perform body and inc while
  433.     test is TRUE.  This is equivalent to:
  434.     init (while test { body inc })
  435.   break will terminate the loop and continue will jump to inc.
  436.   For example:
  437.     (int j)
  438.     (for (j 1) (< j 6) (+= j 1)
  439.     {
  440.       (if (== j 3)(continue))    ; skip 3
  441.       (msg j)
  442.     })
  443.     prints out: 1 2 4 5
  444.   See also: break, continue, while.
  445.  
  446. (goto label)                             [TOKEN : zip]
  447.   Even if you dare, use this with care.
  448.   Don't cross defun boundaries.
  449.   See also: label.
  450.  
  451. (halt)                                   [zip : zip]
  452.   Halt the Mutt machine.  This stops any program that is running and
  453.     returns control to the application.
  454.   See also: done.
  455.  
  456. (if test true [false])         [BOOLEAN, block, block : last block executed]
  457.   test and true must exist even if blank (ie "{}" or "()").
  458.   eg (if (== foo bar) (msg "foo == bar") (msg "foo != bar") )
  459.      (== foo bar)(if () (msg "foo == bar"))
  460.   The C conditional expression "condition ? true : false" can be mimiced
  461.     with (if condition true false).
  462. (include filename)                      [TOKEN|STRING : zip]
  463.   Compile another file.  After filename is compiled,  compiling  resumes
  464.     at the line after the one that contained the include.
  465.     ie  "(include foo.mut)" is the same as "(include foo ; doo daa"
  466. (insert-object object-name n new-object ...)
  467.                     [LIST NUMBER any [any ...] : LIST]
  468.                   [STRING NUMBER STRING [STRING ...] : STRING]
  469.   Insert an object into another object after the nth element.
  470.   To prepend an object, use n == -1.
  471.   You can put the following types into a list: STRING, NUMBER, LIST.
  472.     Mix and match as much as you like.
  473.   Example:
  474.     (list L)
  475.     (insert-object L 0 "123" 5 6) => ["123" 5 6]
  476.     (insert-object L 0 4)         => ["123" 4 5 6]
  477.     (insert-object L 555 7)      => ["123" 4 5 6 7]
  478.   See also:  extract-element, remove-elements, length-of, list, string.
  479. (int name [name ...])                 [TOKEN [TOKEN ...] : zip]
  480.   Evaluation: var                      [TOKEN : NUMBER]
  481.   Assignment: (var value)               [TOKEN NUMBER : NUMBER]
  482.   Create 32 bit integer variables.
  483.   The range of a int is [-2,147,483,648 : 2,147,483,647].
  484.   See also: bool, byte, small-int, string, array.
  485. (small-int name [name ...])             [TOKEN [TOKEN ...] : zip]
  486.   Evaluation: var                      [TOKEN : NUMBER]
  487.   Assignment: (var value)               [TOKEN NUMBER : NUMBER]
  488.   Create 16 bit integer variables.  The only advantage of using small-int
  489.     instead of int is that small-ints require less memory to store (and
  490.     it might take less time to store and retrieve them).
  491.   The range of a small-int is [-32,768 : 32,767].
  492.   Note that a NUMBER may not fit in a small-int.  If not, the number
  493.     will be truncated to fit.
  494.   See also: bool, byte, int, string, array.
  495.  
  496. (label label-name)                         [TOKEN : zip]
  497.   The target of a goto.
  498.   eg (label foo)(goto foo) creates an infinite loop.
  499.   See also: goto.
  500. (length-of name)                        [any : NUMBER]
  501.   Return the lenght of a object.
  502.   Type        Length
  503.   ----        ------
  504.   STRING    Number of characters in the string.  eg "foo" => 3.
  505.   LIST        Number of elements in the list.
  506.         eg ["one" 2 "three"] => 3.
  507.   See also: list, insert-object.
  508. (list name [name ...])                 [TOKEN [TOKEN ...] : zip]
  509.   Create one or more list variables.  If in a defun, the variable is
  510.     local to that defun, otherwise it is global.
  511.   Example:
  512.     (list L) creates a list named L.
  513.     (insert-object L 0 "123" 5 6) puts 3 elements in to L:  ["123" 5 6]
  514.   See also:  string, extract-element, insert-object, length-of,
  515.     remove-elements.
  516. (loc var)                            [TOKEN : BLOB]
  517.   Return the address of a variable.  In this way you can modify the
  518.     variables you pass to functions.
  519. !!!???
  520.   loc works on the following types:  byte, int, small-int, bool and arrays.
  521.   Example:
  522.     (int a b c d)    ; 4 ints in row.  Same order as (array int a 4)
  523.     (defun
  524.       MAIN
  525.       {
  526.     (a 123)(foo (loc a))(msg "a = " a "   b = " b)
  527.     (bar (loc a))
  528.       }
  529.       foo (array int x 2)  ; first element of x maps to a
  530.       {
  531.     (msg "(x 0) = " (x 0))    ; display the value of a
  532.     (x 0 456)        ; set a to 456
  533.     (x 1 111)        ; set b to 111
  534.       }
  535.       bar (pointer int x)
  536.     { (msg "x = " (x)) }    ; display the value of a
  537.     )
  538.     When this is run it produces:
  539.     (x 0) = 123
  540.     a = 456   b = 111
  541.     x = 456
  542.   See also: arg, defun, floc, pointer.
  543.  
  544. (msg stuff)                      [any class ... : STRING]
  545.   Prints a message.  The list is concatenation of the arg list.
  546.   Returns the entire message.
  547.   eg (msg "foo = " foo)
  548.   Note: (msg) is the same as (msg "").
  549.  
  550. (nargs)                                [zip : NUMBER]
  551.   Return the number of parameters passed to the functi;on.
  552.   eg (foo 1 "two" (three)) has 3 arguments and (nargs) returns 3.
  553.   See also: arg.
  554. (not value)                           [BOOLEAN : BOOLEAN]
  555.   Negate value.
  556.   For example: (not (== foo 1)) returns TRUE if foo not equal to 1.
  557. (novalue)                              [zip : VOID]
  558.   A way to make sure a function returns VOID.
  559.  
  560. (or value ...)                 [BOOLEAN [BOOLEAN ...] : BOOLEAN]
  561.   Logically or a bunch of things.
  562.   The first TRUE value will terminate (ie the rest of the or will
  563.     not be evaluated).  eg (or (beginning-of-line) foo)
  564.   For example:
  565.     (or (foo) TRUE (bar)):  If (foo) returns TRUE, the or returns TRUE
  566.     and nothing else is done.  If (foo) return FALSE, the or returns
  567.     TRUE anyway (because of the TRUE).  In all cases, bar is never
  568.     called.
  569.   See also: and.
  570.  
  571. (pointer type var-names)           [TOKEN TOKEN [TOKEN ...] : zip]
  572.   Declare pointer vars.  You can create pointers to byte, small-int,
  573.     int, bool, and defun (functions).
  574.   Pointers to data:
  575.     To get what a pointer points to: (pd)
  576.     Assignment: (pd location) where location is a pointer
  577.       arg or something returned by loc or floc.
  578.   Pointers to functions:
  579.     (pf) calls function pointed to by pf with no args.
  580.     (pf arg1 ... argn) calls pf with n args.
  581.   See also: defun, floc, loc.
  582. (push-arg exp)                         [anything : anything]
  583.   Push a arg onto the function call list.  Useful when you need to call
  584.     a function and you don't what args you need to call it with at
  585.     compile time.
  586.   Example:
  587.     (int j)
  588.     (foo "arg 1"
  589.       (for (j 0) (< j some-num) (+= j 1) (push-arg (peek j)))
  590.     )
  591.     This will call foo with one or more args:  "arg 1" and some-num of
  592.       whatever peek returns.
  593.   See also: push-args.
  594. (push-args n)                           [NUMBER : last arg]
  595.   Push all the args from n back on the stack.  The first arg is 0.
  596.   For example: If max is a function that takes the maximum of all its args,
  597.     and foobar is a function that takes a string and a list of numbers and
  598.     you want to find the maximum of those numbers, you could:
  599.     (defun foo (string s) { (int m) (m (max (push-args 1))) })
  600.   Notes:
  601.     push-args can only be used with defined functions plus concat and msg.
  602.       For example (+ (push-args 3)) is an error, (msg (push-args 3)) is OK.
  603.     If n is greater than the number of args, no args are pushed and no
  604.       error is generated.
  605.     You can treat push-args like a run-of-the-mill arg - eg (foo 123
  606.       (push-args 2) "hoho") and (foo (push-args 4) (push-args 2)) are
  607.       OK.
  608.   See also: push-arg.
  609.  
  610. (remove-elements object n z)        [LIST|STRING NUMBER NUMBER : VOID]
  611.   Remove z elements of a object starting at the nth element.
  612.   If (n >= (length object)), nothing happens.
  613.   (remove-elemenst [] n z):  [].
  614. !!!??? other magic done to n and z?
  615.   Examples:
  616.     (remove-elemenst [1 2 3] 0 1)     => [2 3]
  617.     (remove-elemenst [1 2 3] 1 100)   => [1]
  618.     (remove-elemenst [1 2 3] 100 100) => [1 2 3]
  619.   Notes:
  620.     This doesn't work on string constants (doesn't make sense either).
  621.       ie (remove-elements "123" 1 1) doesn't work.
  622.       (text "123")(remove-elements text 1 1) does.
  623.  
  624. (string name ...)                 [TOKEN [TOKEN ...] : zip]
  625.   Evaluation: var                      [TOKEN : STRING]
  626.   Assignment: (var value)               [TOKEN STRING : STRING]
  627.   Create some strings.  String length is variable ie the string will
  628.     resize it self to hold whatever you want to put in it.
  629.   Example:
  630.     (string foo)
  631.     (foo "this is a test")
  632.     (msg foo)        ;; this will print "this is a test"
  633.   See also:  list, extract-elements, insert-object, length-of,
  634.     remove-elements.
  635. (switch value  value block [value block ...] [default block])
  636. [NUMBER|STRING|BOOLEAN, same, block, same, block ... : last block executed]
  637.   Get a value.  Scan down the list until a matching value is found and then
  638.     execute the next block and exit the switch.
  639.   If no match is found, the default block is executed (if it exists).
  640.   All values must have the same class.
  641.   eg
  642.     (switch (extract-elements (ask "Is the moon made of green cheese? ") 0 1)
  643.       "y" (msg "Not according to current scientific thought.")
  644.       "n" (msg "Probably the case.")
  645.       default (msg "Burp.")
  646.     )
  647.   See also: cond
  648.  
  649. TRUE                               [zip : BOOLEAN]
  650.   The boolean constant TRUE.
  651.   Use this for the default case in cond.
  652.  
  653. (while test body)          [BOOLEAN, block : FALSE (unless break used)]
  654.   Perform body while test is TRUE.
  655.   For example: (int j) (j 0) (while (< j 5) { (msg j) (+= j 1) } )
  656.     will print out: 0 1 2 3 4.
  657.   A do..while loop can be constructed like so:
  658.     (while {body test} ())
  659.   You can use break to get out of the loop or continue to move back to
  660.     test.
  661.   See also: break, continue, for.
  662.  
  663. ====================================================================
  664.              How args are passed
  665. ====================================================================
  666. All args are evaluated before being passed.  bytes, small-ints and ints
  667.   are converted to NUMBER.
  668. Args are passed by value and  reference.  Value  means a copy of the arg
  669.   is pushed on the stack and changes to it will not be reflected  in the
  670.   original.  When  something  is passed by  reference,  a pointer to the
  671.   original is pushed on the stack and changes will be to the original.
  672. - bools, numbers, voids:  value.
  673. - arrays, blobs, strings, lists:  reference.
  674.  
  675. ====================================================================
  676.                  Example PGMS
  677. ====================================================================
  678.     ; Factorial the recursive way
  679. (const NUMBER    0x03)
  680. (defun
  681.   fact    ;; the recursive part.  input: x  output: x!
  682.   {
  683.     (if (== (arg 0) 0) 1        ; 0! = 1
  684.       (* (arg 0) (fact (- (arg 0) 1)))    ; x! = x * (x-1)!
  685.     )
  686.   }
  687.   !    ;; the main routine
  688.   {
  689.     (int x)
  690.     (x (convert-to NUMBER (ask "Take factorial of: ")))
  691.     (msg x "! = " (fact x))
  692.   }
  693.   MAIN { (!) }        ;; (! 5) produces "5! = 120" 
  694. )
  695.  
  696. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  697. (const NUMBER    0x03)
  698. (defun square MAIN        ; print a table of squares
  699. {
  700.   (int foo max)
  701.   (max (convert-to NUMBER (ask "Max = ")))
  702.   (foo 1)
  703.   (while (<= foo max) { (msg foo "\^2 = " (* foo foo)) (+= foo 1) })
  704. })
  705. ; (square 3) produces
  706. ; 1^2 = 1
  707. ; 2^2 = 4
  708. ; 3^2 = 9
  709. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  710. ; Good ol towers of hanoi
  711. ; Usage: (hanoi <n>) where n is the number of discs
  712. (const NUMBER    0x03)
  713. (defun
  714.   print-move (from to) { (msg "Move Disk From " from " To " to) }
  715.   transfer (from to via)(int n)
  716.   {
  717.     (if (== n 1)(print-move from to)
  718.     {
  719.       (transfer from via to (- n 1))
  720.       (print-move from to)
  721.       (transfer via to from (- n 1))
  722.     })
  723.   }
  724.   hanoi MAIN
  725.     { (transfer "A" "B" "C" (convert-to NUMBER  (ask "n = ")))(msg "done.") }
  726. )
  727. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  728. ; tobase(n,base): convert n (base 10) to base.  eg (tobase 10 16) => "A"
  729. ;    C Durland
  730.  
  731. (defun
  732.   mod (int n base)    ; n mod base = n - (n/base)*base
  733.     { (- n (* (/ n base) base)) }
  734.   tobase (int n base)
  735.   {
  736.     (if (< n base) (extract-elements "0123456789ABCDEF" n 1)
  737.       (concat
  738.         (tobase (/ n base) base)    ; tobase n/base base
  739.     (tobase (mod n base) base)    ; tobase (n mod base) base
  740.       )
  741.     )
  742.   }
  743. )
  744. (const NUMBER    0x03)
  745. (defun
  746.   MAIN
  747.   {
  748.     (msg (tobase
  749.     (convert-to NUMBER (ask "n = "))
  750.     (convert-to NUMBER (ask "base = "))))
  751.   })
  752. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  753. (defun sort (array int list 1)(int n)    ; shell sort an array of n ints
  754. {
  755.   (int gap i j k tmp)
  756.   (gap (/ n 2))
  757.   (while (> gap 0)
  758.   {
  759.     (i gap)
  760.     (while (< i n)
  761.     {
  762.       (j (- i gap))
  763.       (while (and (>= j 0) (> (list j) (list (+ j gap))))
  764.       {
  765.     (k (+ j gap))        ;; swap this and the jth element
  766.     (tmp (list j))
  767.     (list j (list k))
  768.     (list k tmp)
  769.     (-= j gap)
  770.       })
  771.       (+= i 1)
  772.     })
  773.     (/= gap 2)
  774.   })
  775. })
  776. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  777.     ; Quick sort.  From Horowitz & Sahni pg 347
  778.     ; Sort list[m..n] into assending order
  779.  
  780.     ; swap is a routine that interchanges list[a] with list[b]
  781.     ; cmp compares list[a] with list[b] and returns:
  782.     ;    negative if list[a] < list[b]
  783.     ;    positive if list[a] > list[b]
  784.     ;    zero     if list[a] = list[b]
  785. (defun
  786.   Qsort (list)(int m n)(pointer defun swap cmp)
  787.   {
  788.     (int i j)
  789.  
  790.     (if (>= m n) (done))    ;; end the recursion
  791.     (i m) (j (+ n 1))
  792.     (while TRUE
  793.     {
  794.       (while { (+= i 1)(and (<= i n) (< (cmp list i m) 0)) } ())
  795.       (while { (-= j 1)(> (cmp list j m) 0) } ())
  796.       (if (< i j) (swap list i j) (break))
  797.     })
  798.     (swap list m j)
  799.     (Qsort list m (- j 1) swap cmp)
  800.     (Qsort list (+ j 1) n swap cmp)
  801.   }
  802. )
  803.     ; swap and cmp routines for arrays of ints
  804. (defun
  805.   swap (array int list 1)(int a b)    ; swap 2 elements
  806.   {
  807.     (int tmp)
  808.     (tmp (list a)) (list a (list b)) (list b tmp)
  809.   }
  810.   cmp (array int list 1)(int a b)    ; compare 2 elements
  811.     { (- (list a) (list b)) }
  812. )
  813.  
  814. ; (array int list 100)
  815. ; (Qsort list 0 n (floc swap) (floc cmp))
  816.  
  817. ======================================================================
  818.                Notes and Tricks
  819. ======================================================================
  820. * Lets say you have a number and wish to turn it into a string with a
  821.   leading zero if it is less than 10.
  822.     (int n)(string s 20)
  823.     (n (convert-to NUMBER (ask "n = ")))
  824.     (s (concat (if (< n 10) ("0")("")) n))
  825.   This trick also works in msgs, etc.
  826. * In general, only the last thing in a block matters.
  827.   So, (foo { (msg "set foo to 123") 123 }) is the same as
  828.     (msg "set foo to 123") (foo 123).
  829.  
  830. ======================================================================
  831.               The Mutt Compiler
  832. ======================================================================
  833.    Since Mutt is a compiled langauge, you'll need to compile the
  834. programs you've written before you can run them.  To do this use MC2,
  835. the Mutt2 Compiler.  Type "mc2 filename".  filename is assumed to have a
  836. .MUT extension (ie you don't have to type it).  The compiler produces an
  837. output file in the current directory with the name name.MCO (where name
  838. is the same base name as filename).
  839.   MC2 options:
  840.     -I directory-name
  841.        An alternate directory for include files.  For example, if
  842.      foo.mut is in directory fred and contains (include sam.mut) and
  843.      sam.mut is in directory /bar then you need mc -I/bar foo.
  844.     -l
  845.        Produce a list file showing the compiler output (name.LST).
  846.     -t tname
  847.        Use external token file tname.TOK.  This a code crunching
  848.      option.  Useful when Mutt is used as an imbedded langauge.
  849.      Normally, when MC can't resolve a function call (to an external
  850.      function), the name is looked up at runtime.  This has two
  851.      disadvantages - the name takes up space and it takes time to
  852.      look up the name.  The token file tells MC where the external
  853.      functions are located and avoids these problems.  It is only
  854.      used at compile time.
  855.     -v
  856.        Display the version of the compiler.
  857.  
  858.    You can run your compiled program in one of two ways:  If Mutt is
  859. imbedded in another program, read the documentation on that program to
  860. find out how to load and run Mutt programs.  If you are using Mutt
  861. standalone (using just the functions contained in this documentation)
  862. then use MM2 (the Mutt2 Machine).  Type "mm2 fname" where fname is the
  863. name of the file you compiled.
  864.  
  865. For example, to compile and run the factorial pgm listed above:
  866.   mc2 fact            ; type this to compile the fact program
  867.   Mutt2 compiler 10/16/91
  868.   Errors: 0  Warnings: 0. Code size = 99 bytes.
  869.  
  870.   mm2 fact            ; type this to run the fact program
  871.   Take factorial of: 5        ; user is prompted for a value and types 5
  872.   5! = 120            ; the answer is printed out
  873.  
  874. ======================================================================
  875.                    Gotchas
  876. ======================================================================
  877. * Be careful of name overlap.  Note that the following progam is legal
  878.   but may not do what you think.
  879.      (const foo 123)
  880.      (defun foo
  881.      {
  882.        (int foo)
  883.        (foo foo)    ; what does this line really do???
  884.      })
  885.  
  886. ======================================================================
  887. ======================================================================
  888.